<?php
namespace app\common\components;

use Closure;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use think\facade\Log;

class Mail
{

    //服务地址端口 *
    protected static $Host;
    protected static $Port;

    //账户密码 *
    protected static $Username;
    protected static $Password;

    //激活LLS加密
    protected static $SMTPSecure;

    //设置编码
    protected static $CharSet = 'utf-8';

    //邮件实例
    private $_mail;

    /**
     * @var Closure[]
     */
    protected static $maker = [];

    /**
     * 构造方法
     * @access public
     */
    public function __construct()
    {
        if (!empty(static::$maker)) {
            foreach (static::$maker as $maker) {
                call_user_func($maker, $this);
            }
        }

        //判断属性
        if (static::$Host === null || static::$Port === null) {
            throw new Exception('Mail::$Host and Mail::$Port must be set.');
        }
        if (static::$Username === null || static::$Password === null) {
            throw new Exception('Mail::$Username and Mail::$Password must be set.');
        }
    }

    /**
     * 设置服务注入
     * @access public
     * @param Closure $maker
     * @return void
     */
    public static function maker(Closure $maker)
    {
        static::$maker[] = $maker;
    }



    /**
     * 设置编码格式
     */
    public static function setCharset(string $charset){
        static::$CharSet = $charset;
    }
    /**
     * 设置加密协议
     */
    public static function setEncryption(string $encypt){
        static::$SMTPSecure = $encypt;
    }

    /**
     * 设置服务器地址与端口
     */
    public static function setHostAndPort(string $host, string $post){
        static::$Host = $host;
        static::$Port = $post;
    }
    /**
     * 设置用户名密码
     */
    public static function setUsernameAndPassword(string $username, string $password){
        static::$Username = $username;
        static::$Password = $password;
    }


    //创建邮件实例
    private function newMail(){
        $mail = new PHPMailer(true);
        $mail->isSMTP();
        $mail->SMTPAuth = true;
        $mail->CharSet = static::$CharSet;

        if ( isset(static::$SMTPSecure) )
            $mail->SMTPSecure = static::$SMTPSecure;


        $mail->Host = static::$Host;
        $mail->Port = static::$Port;
        $mail->Username = static::$Username;
        $mail->Password = static::$Password;

        return $this->_mail = $mail;
    }

    /**
     * @param array $from #发送方 如：['address'=>'123@163.com', 'name'=>'李四'] 或 ['address'=>'123@163.com']
     * @param array $to #接收方
     *         如：[
     *              '123@163.com',
     *              '123@163.com'
     *            ]
     * @param array|null $replyTo #回复地址 如：['address'=>'123@163.com', 'name'=>'李四'] 或 ['address'=>'123@163.com']
     * @param array|null $cc #抄送 如：同上
     * @param array|null $bcc#加密抄送 如：同上
     * @throws Exception
     */
    public function setMail(array $from, array $to, array $replyTo = null, array $cc = null, array $bcc = null){
        $mail = $this->newMail();
        $mail->setFrom($from['address'], $from['name'] ?? '');
        foreach ($to as $v){
            $mail->addAddress($v);
        }

        //可选项
        if (!empty($replyTo))
            $mail->addReplyTo($replyTo['address'], $replyTo['name'] ?? '');
        if (!empty($cc))
            $mail->addCC($cc['address'], $cc['name'] ?? '');
        if (!empty($bcc)){
            $mail->addBCC($bcc['address'], $bcc['name'] ?? '');
        }
    }


    /**
     * #发送邮件
     * @param string $subject 邮件主题
     * @param string $body   邮件主体
     * @param array $attachmets   附件 [ ['FullPath'=>'/a.jpg', 'name'=>'图片'] ]
     * @param bool $isHtml  邮件格式默认html
     * @return bool 发送成功返回true 否则返回false
     */
    public function sendMail(string $subject, string $body, array $attachmets = null,bool $isHtml = true){
        $mail = $this->_mail;

        //标题
        $mail->Subject = $subject;

        //内容
        if ($isHtml){
            $mail->Body = $body;
        }else{
            $mail->isHTML(false);
            $mail->AltBody = $body;
        }

        //附件
        if ( !empty($attachmets) && is_array($attachmets) ){
            foreach ($attachmets as $attachmet){
                $mail->addAttachment($attachmet['address'], $attachmet['name'] ?? '');
            }
        }

        // 发送邮件
        if(!$mail->send()){
            Log::warning($mail->ErrorInfo);
            return false;
        }else{
            return true;
        }

    }



}